﻿
using Patterns4Net.ArchitectureExplorer.Infrastructure.Config;

namespace Patterns4Net.ArchitectureExplorer.Infrastructure
{
    using System;
    using System.Collections.Generic;
    using Diagram.Relations;

    /// <summary>
    /// Represents a configuration of Architecture Explorer. 
    /// Settings can be serialized and deserialized into an xml file 
    /// using the <see cref="SettingsSerializer"/> class.
    /// </summary>
    /// <remarks>
    /// <para>Creation policy for this class in the MEF is set to shared, 
    /// which is similar to singleton object. But it's export is not configured via attributes, 
    /// it is done by hand in <see cref="AppBootstrapper"/>.</para>
    /// </remarks>
    public class Settings
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Settings"/> class 
        /// and sets up default values for all settings.
        /// </summary>
        public Settings()
        {
            this.ShowAlwaysRelations = new List<Type> { typeof (Inheritance) };
            this.UseGraphRatio = false;
            this.SetUpDefaultGraphAttributes();
            this.SetUpDefaultIgnoredNamespaces();
            this.SetUpDefaultIgnoredTypes();
            this.SetUpDefaultIgnoredMembers();
        }

        /// <summary>
        /// Gets the relations that should always be visible if two 
        /// nodes that are connected with such relation are present in the graph.
        /// </summary>
        /// <remarks>
        /// <para>This option is not supported in xml configuration.</para>
        /// </remarks>
        public IList<Type> ShowAlwaysRelations { get; private set; }

        /// <summary>
        /// Gets the starts of names of namespaces that should be ignored.
        /// </summary>
        public IList<string> IgnoredNamespaces { get; private set; }

        /// <summary>
        /// Gets the regular expressions for names of types (classes, interfaces, structures) that should be ignored.
        /// </summary>
        public IList<string> IgnoredTypes { get; private set; }

        /// <summary>
        /// Gets the regular expressions for names of members (properties and methods) that should be ignored.
        /// </summary>
        public IList<string> IgnoredMembers { get; private set; }

        /// <summary>
        /// Gets or sets a value indicating whether a graph ratio parameter should be used for DOT.
        /// </summary>
        /// <remarks>
        /// <para>This option is not supported in xml configuration.</para>
        /// </remarks>
        public bool UseGraphRatio { get; set; }

        /// <summary>
        /// Gets the attributes that will be added to the input for DOT.
        /// </summary>
        public IDictionary<string, string> AdditionalGraphAttributes { get; private set; }

        /// <summary>
        /// Sets up default value for <see cref="IgnoredNamespaces"/>
        /// </summary>
        public void SetUpDefaultIgnoredNamespaces()
        {
            this.IgnoredNamespaces = new List<string> { "Contracts", "XamlGeneratedNamespace" };
        }

        /// <summary>
        /// Sets up default value for <see cref="IgnoredTypes"/>.
        /// </summary>
        public void SetUpDefaultIgnoredTypes()
        {
            this.IgnoredTypes = new List<string> { "<.*" };
        }

        /// <summary>
        /// Sets up default value for <see cref="IgnoredMembers"/>.
        /// </summary>
        public void SetUpDefaultIgnoredMembers()
        {
            this.IgnoredMembers = new List<string> { "<.*" };
        }

        /// <summary>
        /// Sets up default value for <see cref="AdditionalGraphAttributes"/>.
        /// </summary>
        public void SetUpDefaultGraphAttributes()
        {
            this.AdditionalGraphAttributes = new Dictionary<string, string> { {"rankdir", "BT"} };
        }
    }
}
